﻿using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace AutoCadConvert
{
    public class Point : BspObject, ICloneable
    {
        public double X;//点的X坐标
        public double Y;//点的Y坐标
        public double Z;//点的Z坐标
        public int refCount;//点的度
        public int index;//点的索引
        public bool IsLogicPoint =false;

        public Point() { }
        public Point(Point pt)
        {
            X = pt.X;
            Y = pt.Y;
            Z = pt.Z;
            refCount = pt.refCount;
            index = pt.index;
            IsLogicPoint = pt.IsLogicPoint;
        }
        public Point(Autodesk.AutoCAD.Geometry.Point3d pt,bool isLogic = false)
        {
            X = Math.Round(pt.X, base.iPresicion);
            Y = Math.Round(pt.Y, base.iPresicion);
            Z = Math.Round(pt.Z, base.iPresicion);
            refCount = 1;
            index = -1;
            IsLogicPoint = isLogic;
        }

        public override bool Equals(object obj)
        {
            if (obj is Point)
                return (X == ((Point)obj).X && Y == ((Point)obj).Y && Z == ((Point)obj).Z) ? true : false;
            else if (obj is Point3d)
                return (X == ((Point3d)obj).X && Y == ((Point3d)obj).Y && Z == ((Point3d)obj).Z) ? true : false;
            else
                return false;
        }
        public double Distance
        {
            get { return Math.Sqrt(Math.Pow(this.X, 2) + Math.Pow(this.Y, 2)); }
        }
        public double Rotation
        {
            get { return (X == 0 ? 90.0 : Math.Atan(Y / X)); }
        }
        #region 重写运算
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        public string To3DString()
        {
            return string.Format("X={0} Y={1} Z={2}", X * Unit, Y * Unit, Z * Unit);
        }
        public new string ToString()
        {
            return string.Format("X={0} Y={1}", X * Unit, Y * Unit);
        }
        public static bool operator ==(Point pt1, Point pt2)
        {
            if (pt1 is Point && pt2 is Point)
                return (pt1.X == ((Point)pt2).X && pt1.Y == ((Point)pt2).Y && pt1.Z == ((Point)pt2).Z) ? true : false;
            else if(!(pt1 is Point) && !(pt2 is Point))
                return true;
            else
                return false;
        }
        public static bool operator !=(Point pt1, Point pt2)
        {
            if (pt1 is Point && pt2 is Point)
                return (pt1.X != ((Point)pt2).X || pt1.Y != ((Point)pt2).Y || pt1.Z != ((Point)pt2).Z) ? true : false;
            else if (!(pt1 is Point) && !(pt2 is Point))
                return false;
            else
                return true;
        }
        public static Point operator /(Point pt, double value)
        {
            return new Point() { X = pt.X / value, Y = pt.Y / value, Z = pt.Z / value,refCount = pt.refCount, index = pt.index };
        }
        public static Point operator *(Point pt, double value)
        {
            return new Point() { X = pt.X * value, Y = pt.Y * value, Z = pt.Z * value, refCount = pt.refCount, index = pt.index };
        }
        public static Point operator +(Point pt1, Point pt2)
        {
            return new Point() { X = pt1.X + pt2.X, Y = pt1.Y + pt2.Y, Z = pt1.Z + pt2.Z,refCount = pt1.refCount, index = pt1.index };
        }
        public static Point operator -(Point pt1, Point pt2)
        {
            return new Point() { X = pt1.X - pt2.X, Y = pt1.Y - pt2.Y, Z = pt1.Z - pt2.Z, refCount = pt1.refCount, index = pt1.index };
        }
        public void Offset(Point pt)
        {
            this.X -= pt.X;
            this.Y -= pt.Y;
        }
        #endregion

        public override IEnumerable<XElement> ToXml()
        {
            return new XElement[] {
                new XElement("RefCount",refCount),
                new XElement("Pos",new XText(string.Format("X={0} Y={1}",X*Unit,Y*Unit))),
                new XElement("IsLogicPoint",IsLogicPoint?1:0),
            };
        }
        public override IEnumerable<BspObject> FromXml(XElement node)
        {
            this.refCount = Convert.ToInt32(node.Element("RefCount").Value);
            string[] posStr = node.Element("Pos").Value.Split(new char[] { '=',' ' });
            this.X = Convert.ToDouble(posStr[1]);
            this.Y = Convert.ToDouble(posStr[3]);
            this.Z = 0;
            this.IsLogicPoint = Convert.ToBoolean(node.Element("IsLogicPoint").Value);
            yield return this;
        }
        public Autodesk.AutoCAD.Geometry.Point3d ToPoint3d()
        {
            return new Autodesk.AutoCAD.Geometry.Point3d(new double[] { X,Y,Z});
        }

        public Point ToMirror()
        {//取镜像
            return new Point() { X = this.Y, Y = this.X,Z=this.Z,refCount=this.refCount,index=this.index,IsLogicPoint=this.IsLogicPoint };
        }
        public void SetMirror()
        {
            Point pt = new Point(this).ToMirror();
            this.X = pt.X;
            this.Y = pt.Y;
        }
        public object Clone()
        {//深拷贝
            return new Point(this);
        }
    }
}
